package com.zx.flow.core.execute.eventhandler;

import com.zx.flow.api.dict.FlowDict.Event;
import com.zx.flow.api.execute.model.FlowContext;
import com.zx.flow.api.execute.model.FlowNode;
import com.zx.flow.api.execute.model.FlowOperator;
import com.zx.flow.api.execute.request.FlowParamOperator;
import com.zx.flow.api.execute.response.FlowResult;
import com.zx.flow.api.util.AssertUtil;
import com.zx.flow.core.execute.EventHandler;
import java.util.List;
import java.util.Objects;
import org.springframework.util.CollectionUtils;

/**
 * 事件处理器【流程->修改操作人】
 */
public class EventFlowOperatorHandler extends EventHandler<FlowParamOperator> {

    @Override
    public boolean in(FlowContext flow, FlowParamOperator param) {
        AssertUtil.checkEvent(param.getEvent(), Event.nodeAppendOperator, Event.nodeRemoveOperator);
        AssertUtil.checkOperator(flow, param.getNodeId(), param.getAccountCode());
        return flow != null;
    }

    @Override
    public FlowResult on(FlowContext flow, FlowParamOperator param) {
        Event event = Event.getByCode(param.getEvent());
        // 获得当前节点
        FlowNode currNode = AssertUtil.checkCurrentNodeId(flow, param.getNodeId());
        if (Objects.equals(event, Event.nodeAppendOperator)) {
            append(currNode, param.getOperators());
        } else if (Objects.equals(event, Event.nodeRemoveOperator)) {
            remove(currNode, param.getOperators());
        } else {
            AssertUtil.throwFE("事件不支持, event=" + event);
        }
        // 触发监听
        this.listener(currNode, event);
        return FlowResult.ok(flow);
    }

    /**
     * 追加操作人
     *
     * @param node
     * @param appendList
     */
    public void append(FlowNode node, List<FlowOperator> appendList) {
        List<FlowOperator> operators = node.getOperators();
        if (CollectionUtils.isEmpty(operators)) {
            node.setOperators(appendList);
            return;
        }
        // 校验是否有交集
        AssertUtil.checkNotIntersection(operators, appendList, "操作人已经存在");
        operators.addAll(appendList);
    }

    /**
     * 删除操作人
     *
     * @param node
     * @param removeList
     */
    public void remove(FlowNode node, List<FlowOperator> removeList) {
        List<FlowOperator> operators = node.getOperators();
        AssertUtil.checkNotEmpty(operators, "操作人列表为空，无法移除操作人");
        // 校验removeList 必须是 operators 子集。缺一个也不行
        AssertUtil.checkNotContains(operators, removeList, "操作人不存在, 无法移除操");
        // 删除操作人
        operators.removeAll(removeList);
    }

}
